package com.hhck.service.impl;

import com.alibaba.fastjson.JSON;
import com.hhck.constants.Constants;
import com.hhck.entity.Auth;
import com.hhck.mapper.AuthMapper;
import com.hhck.service.AuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

// 指定缓存的名称（数据保存到redis中key的前缀，一般是标注注解类的全路径）
@CacheConfig(cacheNames = "com.hhck.service.AuthServiceImpl")
@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    private AuthMapper authMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 根据用户id查询菜单树
     */
    @Override
    public List<Auth> queryAuthTreeByUserId(Integer userId) {

        // 从Redis中查询缓存的菜单树
        String authTreeJSON = redisTemplate.opsForValue().get(Constants.AUTH_TREE_PREFIX + userId);
        // 判断是否有缓存数据
        if (StringUtils.hasText(authTreeJSON)) {
            // 有菜单树缓存，直接返回数据
            return JSON.parseArray(authTreeJSON, Auth.class);
        }

        // 程序执行到这里。说明没有菜单树的缓存

        // 查询用户所有的权限
        List<Auth> authList = authMapper.selectAuthByUserId(userId);
        // 将用户权限分级，转换为菜单树
        List<Auth> authTree = authListToTree(authList, 0);
        // 将当前登录用户菜单树存入缓存（权限不经常更新，存入缓存减少数据库压力），设置过期时间
        redisTemplate.opsForValue().set(Constants.AUTH_TREE_PREFIX + userId, JSON.toJSONString(authTree), 60 * 30, TimeUnit.SECONDS);

        return authTree;
    }

    /**
     * 查询所有权限菜单树
     */
    // 声明存入缓存的key
    @Cacheable("'all:auth'")
    @Override
    public List<Auth> queryAllAuthTree() {

        // 查询所有权限
        List<Auth> authList = authMapper.selectAllAuth();
        // 转换成菜单树
        List<Auth> authTree = authListToTree(authList, 0);

        return authTree;
    }

    /**
     * 将用户权限转为菜单树
     */
    private List<Auth> authListToTree(List<Auth> authList, Integer parentId) {

        // 创建菜单树（第一次进入此方法时为一级菜单）
        List<Auth> authTree = new ArrayList<Auth>();

        // 遍历用户所有的权限
        for (Auth auth : authList) {
            // 菜单分级
            if (auth.getParentId().equals(parentId)) {
                // 将拥有同一个父id的权限放入同一级菜单中（一级菜单的父id为0）
                authTree.add(auth);
            }
        }

        // 遍历当前级菜单树（第一次进入此方法时为一级菜单）
        for (Auth auth : authTree) {
            // 递归此方法
            // 再次遍历用户所有的权限，并将所有父id为当前菜单id的权限存入下一级菜单集合中
            List<Auth> childAuthList = authListToTree(authList, auth.getAuthId());
            // 将返回的下一级菜单（二级菜单）设置为当前菜单（一级菜单）的子菜单
            auth.setChildAuth(childAuthList);
        }

        return authTree;
    }

}

